package com.fang.security.security.filter;

import com.fang.security.common.CommonConstants;
import com.fang.security.common.exception.RException;
import com.fang.security.entity.DO.SysUser;
import com.fang.security.entity.bo.security.UserRole;
import com.fang.security.security.utils.SpringContextUtil;
import com.fang.security.service.SysUserService;
import com.fang.security.service.security.AuthorityService;
import com.fang.security.utils.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * @Description
 * @Author Bernie
 * @Date 2024/4/17 17:53
 **/
@Slf4j
public class JwtAuthenticationTokenFilter extends BasicAuthenticationFilter {

    private SysUserService sysUserService;

    private AuthorityService authorityService;

    public JwtAuthenticationTokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
        // 使用context手动注入
        this.sysUserService = SpringContextUtil.getBean(SysUserService.class);
        this.authorityService = SpringContextUtil.getBean(AuthorityService.class);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        final String token = request.getHeader(CommonConstants.CommonRequest.AUTHORIZATION);
        //判断当前请求中包含令牌
        if (StringUtils.isNotBlank(token)) {
            //重token中获取用户的角色权限信息
            try {
                if (!JWTUtil.verify(token)) {
                    log.info("verify token fail ===>");
                    filterChain.doFilter(request, response);
                    return;
                }
                String userId = JWTUtil.getUserId(token);
                String username = JWTUtil.getUsername(token);
                SysUser sysUser = sysUserService.selectByName(username);
                List<UserRole> userRoles = authorityService.selectUserRoleByUserID(userId);
                if (sysUser != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                    // 角色需要添加前缀："ROLE_"
                    userRoles.forEach(userRole -> {
                        userRole.setRoleCode(CommonConstants.Role.NAME_PREFIX + userRole.getRoleCode());
                    });
                    //把用户权限信息放到上下文中
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(sysUser, userId, userRoles);
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            } catch (RException e) {
                log.error("JWTUtil 验证出错==>");
            }
        }
        filterChain.doFilter(request, response);
    }

}
